package cn.jiangjiesheng.bootstrap.integration.audit.aspect;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONUtil;
import cn.jiangjiesheng.bootstrap.integration.audit.annotation.RequestAuditing;
import cn.jiangjiesheng.bootstrap.integration.audit.repository.AuditLogRepository;
import cn.jiangjiesheng.bootstrap.integration.audit.po.AuditLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Slf4j
@Aspect
@Component
public class RequestAuditingAspect {

    @Autowired
    private AuditLogRepository auditLogRepository;

    @Around("@annotation(cn.jiangjiesheng.bootstrap.integration.audit.annotation.RequestAuditing)")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        RequestAuditing requestAuditing = signature.getMethod().getAnnotation(RequestAuditing.class);
        if (!requestAuditing.enable()) {
            return point.proceed();
        } else {
            StopWatch stopWatch = new StopWatch();
            AuditLog auditLog = new AuditLog();
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) ra;

            // 执行方法前
            auditLog.setRequest(JSONUtil.toJsonStr(point.getArgs()));
            // 执行目标方法
            Object result = point.proceed();
            // 执行方法后
            auditLog.setResponse(JSONUtil.toJsonStr(result));
            auditLog.setPath(sra.getRequest().getRequestURI());
            auditLog.setMethod(sra.getRequest().getMethod());
            auditLog.setQueryParams(sra.getRequest().getQueryString());
            auditLog.setJavaPath(point.getTarget().getClass().getCanonicalName() + "#" + signature.getName());
            auditLog.setDateTime(DateUtil.formatDateTime(DateUtil.date()));
            auditLog.setConsumption(stopWatch.getTotalTimeMillis() + "ms");
            auditLog.setId(UUID.fastUUID().toString());
            log.info("auditing {}", JSONUtil.toJsonPrettyStr(auditLog));
            auditLog.setTag(requestAuditing.tag());
            auditLogRepository.save(auditLog);
            return result;
        }
    }

}
